﻿using System;
using System.Collections.Generic;
using System.Text;
using GeneratorLibrary.ClassGeneratorLibrary;
using EnvDTE;
using System.IO;

namespace GeneratorAddin {
    public class ProjectAddinInterface : IProjectInterface, IReferenceSettingProject {
        Project project;
        #region IProjectInterface Members

        public string GetRootNameSpace(string path) {
            return project.Properties.Item("RootNamespace").Value.ToString();
        }

        public string Directory {
            get { 
                return project.Properties.Item("FullPath").Value.ToString();
            }
        }

        public void AddFromFile(List<string> path, string file) {
            ProjectItems pi = project.ProjectItems;
            for (int i = 0; i < path.Count; i++) {
                pi = pi.Item(path[i]).ProjectItems;
            }
            pi.AddFromFile(file);
        }

        public void AddFolder(string NewFolder, List<string> path) {
            ProjectItems pi = project.ProjectItems;
            for (int i = 0; i < path.Count; i++) {
                pi = pi.Item(path[i]).ProjectItems;
            }
            pi.AddFolder(NewFolder, EnvDTE.Constants.vsProjectItemKindPhysicalFolder);
        }
        public void DeleteFile(List<string> path, string file) {
            DeleteItem(path, file);
        }
        public void DeleteFolder(List<string> path, string folder) {
            DeleteItem(path, folder);
        }
        private void DeleteItem(List<string> path, string item) {
            ProjectItems pi = project.ProjectItems;
            for (int i = 0; i < path.Count; i++) {
                pi = pi.Item(path[i]).ProjectItems;
            }
            pi.Item(item).Delete();
        }
        public bool AllowOverrideNamespace {
            get {
                return false;
            }
        }
        public List<string> GetReferences() {
            
            if (project.Object is VSLangProj.VSProject) {
                VSLangProj.VSProject vsproject = (VSLangProj.VSProject)project.Object;
                List<string> list = new List<string>();
                foreach (VSLangProj.Reference reference in vsproject.References) {
                    if (reference.StrongName)//System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A
                        list.Add(reference.Identity + "=" + 
                            reference.Identity + 
                            ", Version=" + reference.Version + 
                            ", Culture=" + (string.IsNullOrEmpty(reference.Culture) ? "neutral" : reference.Culture) + 
                            ", PublicKeyToken=" + reference.PublicKeyToken);
                    else
                        list.Add(reference.Identity + "=" + reference.Path);
                }
                return list;
            } else if (project.Object is VsWebSite.VSWebSite) {
                VsWebSite.VSWebSite vswebsite = (VsWebSite.VSWebSite)project.Object;
                List<string> list = new List<string>();
                foreach (VsWebSite.AssemblyReference reference in vswebsite.References) {
                    string value = "";
                    if (reference.FullPath != ""){
                        FileInfo f = new FileInfo(reference.FullPath + ".refresh");
                        if (f.Exists){
                            using (FileStream stream = f.OpenRead()) {
                                using (StreamReader r = new StreamReader(stream)) {
                                    value = r.ReadToEnd().Trim();
                                }
                            }
                        }
                    }
                    if (value == "") {
                        list.Add(reference.Name + "=" + reference.StrongName);
                    } else {
                        list.Add(reference.Name + "=" + value);
                    }
                }
                return list;
            } else {
                throw new Exception("Currently, system is only set up to do references for normal projects.");
            }
        }
        public void RemoveReference(string referenceStrIdentity, string browseUrl) {
            if (project.Object is VSLangProj.VSProject) {
                VSLangProj.VSProject vsproject = (VSLangProj.VSProject)project.Object;
                VSLangProj.Reference reference = null;
                try {
                    reference = vsproject.References.Find(referenceStrIdentity);
                } catch (Exception ex) {
                    //it failed to find one, so it must not exist. But it decided to error for the fun of it. :)
                }
                if (reference != null) {
                    reference.Remove();
                } else {
                    throw new Exception("Reference doesn't exist...?");
                }
            } else if (project.Object is VsWebSite.VSWebSite) {
                VsWebSite.VSWebSite vswebsite = (VsWebSite.VSWebSite)project.Object;
                VsWebSite.AssemblyReference reference = null;
                try {
                    foreach (VsWebSite.AssemblyReference r in vswebsite.References) {
                        if (r.Name == referenceStrIdentity) {
                            reference = r;
                            break;
                        }
                    }
                } catch (Exception ex) {
                    //it failed to find one, so it must not exist. But it decided to error for the fun of it. :)
                }
                if (reference != null) {
                    reference.Remove();
                } else {
                    throw new Exception("Reference doesn't exist...?");
                }
            } else {
                throw new Exception("Currently, system is only set up to do references for normal projects.");
            }
        }
        
        public void AddReference(string referenceStrIdentity, string browseUrl) {
            string path = "";

            if (!browseUrl.StartsWith(referenceStrIdentity)) {
                //it is a path
                path = browseUrl;
            }

            
            if (project.Object is VSLangProj.VSProject) {
                VSLangProj.VSProject vsproject = (VSLangProj.VSProject)project.Object;
                VSLangProj.Reference reference = null;
                try {
                    reference = vsproject.References.Find(referenceStrIdentity);
                } catch (Exception ex) {
                    //it failed to find one, so it must not exist. But it decided to error for the fun of it. :)
                }
                if (reference == null) {
                    if (path == "")
                        vsproject.References.Add(browseUrl);
                    else
                        vsproject.References.Add(path);
                } else {
                    throw new Exception("Reference already exists.");
                }
            } else if (project.Object is VsWebSite.VSWebSite) {
                VsWebSite.VSWebSite vswebsite = (VsWebSite.VSWebSite)project.Object;
                VsWebSite.AssemblyReference reference = null;
                try {
                    foreach(VsWebSite.AssemblyReference r in vswebsite.References){
                        if (r.Name == referenceStrIdentity){
                            reference = r;
                            break;
                        }
                    }
                } catch (Exception ex) {
                    //it failed to find one, so it must not exist. But it decided to error for the fun of it. :)
                }
                if (reference == null) {
                    if (path == "")
                        vswebsite.References.AddFromGAC(browseUrl);
                    else
                        vswebsite.References.AddFromFile(path);
                    
                } else {
                    throw new Exception("Reference already exists.");
                }
            } else {
                throw new Exception("Currently, system is only set up to do references for normal projects.");
            }
        }

        private string GetVersion(string ReferenceStrongName) {
            //System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A
            string []ary = ReferenceStrongName.Split(new char[] {','} );
            foreach(string s in ary){
                string s2 = s.Trim();
                if (s2.StartsWith("Version="))
                    return s2.Remove(0, "Version=".Length);
            }
            return "";
        }
        public bool AllowsReferences() {
            return project.Object is VSLangProj.VSProject || project.Object is VsWebSite.VSWebSite;
        }
        #endregion

        public ProjectAddinInterface(Project p) {
            project = p;
        }




    }
}
